<template>
  <div class="tasks-workspace">
    <header class="workspace-header">
      <div class="header-left">
        <div class="title-block">
          <h2>任务工作台</h2>
          <p class="subtitle">在一个位置管理、筛选、分析并协同处理所有任务</p>
        </div>
      </div>
      <div class="header-right">
        <div class="project-selector-wrapper">
          <label class="project-label">所属项目：</label>
          <el-select
            v-model="selectedProjectId"
            :placeholder="projects.length > 0 ? '请选择项目' : '暂无项目'"
            filterable
            class="project-selector"
            :clearable="false"
            :disabled="projects.length === 0"
            @change="handleProjectChange"
          >
            <el-option
              v-for="project in projects"
              :key="project.id"
              :label="project.name"
              :value="project.id"
            />
          </el-select>
        </div>
        <el-button 
          text
          class="refresh-button"
          @click="handleRefresh"
        >
          <el-icon><Refresh /></el-icon>
          刷新
        </el-button>
        <el-button 
          v-if="canCreate"
          type="primary" 
          class="create-button"
          :disabled="!selectedProjectId"
          @click="handleOpenCreate"
        >
          <el-icon><Plus /></el-icon>
          新建任务
        </el-button>
        <el-radio-group
          v-model="viewModeProxy"
          class="view-switcher"
        >
          <el-radio-button
            v-for="option in viewOptions"
            :key="option.value"
            :label="option.value"
          >
            {{ option.label }}
            </el-radio-button>
          </el-radio-group>
      </div>
    </header>

    <div class="workspace-main">
      <aside :class="['filter-panel', { 'is-collapsed': filterCollapsed }]">
        <header class="filter-header">
          <h3>筛选条件</h3>
          <el-button text size="small" class="collapse-btn" @click="toggleFilterCollapsed">
            <el-icon><DArrowLeft v-if="!filterCollapsed" /><DArrowRight v-else /></el-icon>
            </el-button>
        </header>
        <div class="filter-body" v-show="!filterCollapsed">
          <TaskFilterBar
            :filters="filters"
            :projects="projects"
            :users="users"
            :versions="versions"
            :status-options="taskStatuses"
            :priority-options="priorityOptionsForFilter"
            :current-user-id="currentUserId"
            :selected-project-id="filters.project_id"
            @apply="handleFilterApply"
            @reset="handleFilterReset"
          />
        </div>
      </aside>

      <section class="workspace-content">
        <main class="workspace-body">
          <!-- 初始加载状态 -->
          <PageLoading 
            v-if="initialLoading"
            :title="isRefreshing ? '正在刷新任务数据' : '正在加载任务数据'"
            :subtitle="isRefreshing ? '请稍候，正在更新数据...' : '请稍候，正在为您准备数据...'"
          />
          <transition v-else name="fade-slide" mode="out-in">
            <component
              :is="activeViewComponent"
              :key="`${viewMode}-${statusOptionsKey}`"
              :tasks="tasks"
              :loading="loading"
              :pagination="pagination"
              :status-options="taskStatuses"
              :priority-options="priorityOptionsForList"
              :users="userOptionsForList"
              :users-map="usersMap"
              :selected-ids="selectedIds"
              :batch-loading="batchLoading"
              :status-options-for-batch="taskStatuses"
              :priority-options-for-batch="priorityOptionsForFilter"
              :users-for-batch="users"
              :sort-prop="sortConfig.prop"
              :sort-order="sortConfig.order"
              @page-change="handlePageChange"
              @page-size-change="handlePageSizeChange"
              @select-change="handleSelectionChange"
              @open-detail="handleOpenDetail"
              @delete="handleDelete"
              @refresh="handleRefresh"
              @update-status="handleUpdateStatus"
              @update-priority="handleUpdatePriority"
              @update-assignee="handleUpdateAssignee"
              @split-task="handleSplitTask"
              @create-task="handleCreateTaskFromKanban"
              @batch-update-status="handleBatchUpdateStatus"
              @batch-update-priority="handleBatchUpdatePriority"
              @batch-assign="handleBatchAssign"
              @batch-update-reporter="handleBatchUpdateReporter"
              @batch-update-project="handleBatchUpdateProject"
              @batch-delete="handleBatchDelete"
              @batch-clear="handleClearSelection"
              @download-template="handleDownloadTemplate"
              @import="handleImportFile"
              @export="handleExportTasks"
              @sort-change="handleSortChange"
            />
          </transition>
        </main>
      </section>
      </div>

    <!-- 创建任务对话框 -->
    <CreateTask
      v-model:visible="createDialogVisible"
      :current-user-id="currentUserId"
      :default-project-id="filters.project_id"
      :default-status="quickCreateStatus"
      :status-options="taskStatusesForCreate"
      :priority-options="priorityOptionsForCreate"
      :type-options="typeOptionsForCreate"
      :project-options="projectOptionsForCreate"
      :users="users"
      :common-tag-options="[]"
      @created="handleTaskCreated"
    />

    <!-- 任务详情对话框 -->
    <TaskDetail
      v-if="detailDialogVisible && selectedTaskId"
      :visible="detailDialogVisible"
      :task-id="selectedTaskId"
      :status-options="taskStatusesForCreate"
      :priority-options="priorityOptionsForCreate"
      :users="users"
      :projects="projects"
      @update:visible="handleDetailDialogClose"
      @task-updated="handleTaskUpdated"
    />

    <!-- 任务创建对话框（用于子任务拆分） -->
    <TaskCreateDialog
      v-model="taskSplitDialogVisible"
      :project-id="taskSplitTask?.project_id || ''"
      :default-parent-id="taskSplitTask?.id || ''"
      @success="handleSubTaskCreated"
    />
  </div>
</template>

<script setup lang="ts">
import { ref, reactive, onMounted, computed, watch, h } from 'vue'
import { ElMessage, ElMessageBox } from 'element-plus'
import { Plus, DArrowLeft, DArrowRight, Refresh } from '@element-plus/icons-vue'
import { ElOption, ElSelect } from 'element-plus'
import { useTaskStates } from '@/composables/useTaskStates'
import { useTaskOptions } from '@/composables/useTaskOptions'
import { useUserStore } from '@/stores/user'
import { useTagsStore } from '@/stores/tags'
import { 
  getTasks, 
  deleteTask, 
  updateTaskStatus,
  updateTaskPriority,
  assignTask,
  getTaskStats,
  batchUpdateTasks,
  batchDeleteTasks,
  exportTasks,
  importTasks,
  downloadImportTemplate
} from '@/api/tasks'
import { getProjects } from '@/api/project'
import { getUsers } from '@/api/users'
import { getProjectMembers } from '@/api/project'
import type { ProjectMember } from '@/types/project'
import { versionAPI, type VersionWithStats } from '@/api/version'
import { ResponseParser } from '@/utils/responseParser'
import type { Task, TaskStatus, TaskType, TaskPriority, TaskStats } from '@/types/task'
import type { ProjectResponse as Project } from '@/api/project'
import type { User } from '@/types/user'
import TaskFilterBar from './components/TaskFilterBar.vue'
import TaskListView from './views/TaskListView.vue'
import TaskKanbanView from './views/TaskKanbanView.vue'
import CreateTask from './components/CreateTask.vue'
import TaskDetail from './components/TaskDetail.vue'
import TaskCreateDialog from '@/components/task/TaskCreateDialog.vue'
import PageLoading from '@/components/ui/PageLoading.vue'


// 状态管理
const { statusOptions: taskStatusOptions, loadStates: loadTaskStates } = useTaskStates()
// 任务选项管理（优先级等）
const { 
  priorityOptions: formattedTaskPriorityOptions, 
  loadOptions: loadTaskOptions 
} = useTaskOptions()
// 用户管理
const userStore = useUserStore()
// 标签管理
const tagsStore = useTagsStore()

// 响应式数据
const loading = ref(false)
const batchLoading = ref(false)
const viewMode = ref<'list' | 'kanban'>('list')
const filterCollapsed = ref(false)
const initialLoading = ref(true)
const isRefreshing = ref(false)

// 用于强制更新看板视图的 key，当状态选项变化时更新
const statusOptionsKey = computed(() => {
  return taskStatusOptions.value.map(opt => `${opt.value}:${opt.label}`).join(',')
})

const currentUserId = computed(() => userStore.userInfo?.id ?? '')
const canCreate = computed(() => userStore.hasPermission?.('TASK_CREATE') ?? false)

const viewOptions = [
  { label: '列表', value: 'list', icon: 'List' },
  { label: '看板', value: 'kanban', icon: 'Grid' }
]

const viewComponentMap: Record<'list' | 'kanban', any> = {
  list: TaskListView,
  kanban: TaskKanbanView
}

const activeViewComponent = computed(() => viewComponentMap[viewMode.value] || TaskListView)

// 任务状态选项
const taskStatuses = computed(() => taskStatusOptions.value.filter(status => !status.disabled))

// 格式化优先级选项供列表视图使用（从 useTaskOptions 获取）
const priorityOptionsForList = computed(() => {
  return formattedTaskPriorityOptions.value
})

// 格式化优先级选项供筛选使用（从 useTaskOptions 获取）
const priorityOptionsForFilter = computed(() => {
  return formattedTaskPriorityOptions.value
})

// 任务类型选项（用于创建任务）
const typeOptionsForCreate = computed(() => {
  return [
    { value: 'feature' as TaskType, label: '功能' },
    { value: 'bug' as TaskType, label: '缺陷' },
    { value: 'improvement' as TaskType, label: '改进' },
    { value: 'documentation' as TaskType, label: '文档' },
    { value: 'refactor' as TaskType, label: '重构' },
    { value: 'test' as TaskType, label: '测试' },
    { value: 'other' as TaskType, label: '其他' }
  ]
})

// 格式化状态选项供创建任务使用
const taskStatusesForCreate = computed(() => {
  return taskStatuses.value.map(status => ({
    value: status.value as TaskStatus,
    label: status.label
  }))
})

// 格式化优先级选项供创建任务使用（从 useTaskOptions 获取）
const priorityOptionsForCreate = computed(() => {
  return formattedTaskPriorityOptions.value.map(option => ({
    value: option.value as TaskPriority,
    label: option.label
  }))
})


// 格式化项目选项供创建任务使用
const projectOptionsForCreate = computed(() => {
  return projects.value.map(project => ({
    value: project.id,
    label: project.name
  }))
})

// 格式化用户选项供列表视图使用
const userOptionsForList = computed(() => {
  return users.value.map(user => ({
    id: user.id,
    name: user.name || user.username || ''
  }))
})

// 筛选条件
interface TaskFilters {
  search?: string
  project_id?: string
  version_id?: string
  status?: string
  priority?: string
  assignee_id?: string
  due_date_from?: string
  due_date_to?: string
}

const filters = reactive<TaskFilters>({
  search: undefined,
  project_id: undefined,
  version_id: undefined,
  status: undefined,
  priority: undefined,
  assignee_id: undefined,
  due_date_from: undefined,
  due_date_to: undefined
})

// 选中的项目ID（从筛选条件中获取）
const selectedProjectId = computed({
  get: () => filters.project_id || '',
  set: (value: string) => {
    filters.project_id = value || undefined
  }
})

// 分页
const pagination = reactive({
  page: 1,
  pageSize: 20,
  total: 0
})

// 排序
const sortConfig = reactive({
  prop: '',
  order: ''
})

// 任务数据
const tasks = ref<Task[]>([])
const selectedIds = ref<string[]>([])

// 创建和详情对话框状态
const createDialogVisible = ref(false)
const detailDialogVisible = ref(false)
const selectedTaskId = ref<string>('')
const quickCreateStatus = ref<string>('')
// const selectedAssigneeId = ref('')
// const batchSelectedAssigneeId = ref('')

// 基础数据
const projects = ref<Project[]>([])
const users = ref<User[]>([])
const versions = ref<VersionWithStats[]>([])
// 用户信息映射（用于批量获取的场景，避免单个用户接口调用）
const usersMap = ref<Map<string, User>>(new Map())

// 任务统计
const taskStats = reactive<TaskStats>({
  total: 0,
  tasks_by_status: {},
  overdue: 0
})


// 获取版本列表（可按项目过滤）
const fetchVersions = async (projectId?: string) => {
  try {
    const params: Record<string, unknown> = { limit: 100 }
    if (projectId) {
      params.project_id = projectId
    }
    const versionsResponse = await versionAPI.getVersions(params)
    const parsedVersions = ResponseParser.parseListResponse<VersionWithStats>(versionsResponse)
    versions.value = parsedVersions.items
  } catch (error) {
    console.error('获取版本列表失败:', error)
    versions.value = []
  }
}

// 刷新用户列表（根据当前项目）- 只使用项目成员
const refreshUsers = async () => {
  const projectId = filters.project_id
  try {
    if (projectId) {
      // 如果已选择项目，获取项目成员
      const projectUsers = await loadUsersByProject(projectId)
      users.value = projectUsers
      // 更新用户映射
      usersMap.value.clear()
      projectUsers.forEach(user => {
        usersMap.value.set(user.id, user)
      })
    } else {
      // 如果没有选择项目，清空用户列表
      users.value = []
      usersMap.value.clear()
    }
  } catch (error) {
    console.error('获取项目成员失败:', error)
    users.value = []
    usersMap.value.clear()
  }
}

// Watch监听器引用（用于清理）
const projectIdWatcher = ref<ReturnType<typeof watch> | null>(null)

// 获取任务列表
const fetchTasks = async (isRefresh = false) => {
  if (isRefresh) {
    isRefreshing.value = true
    initialLoading.value = true
  }
  loading.value = true
  try {
    // 修复sort_order类型不匹配的问题
    let sort_order: 'asc' | 'desc' | undefined
    if (sortConfig.order === 'ascending') {
      sort_order = 'asc'
    } else if (sortConfig.order === 'descending') {
      sort_order = 'desc'
    } else {
      sort_order = undefined
    }
    
    // 构建查询参数，将所有筛选条件传递给API
    const params: any = {
      page: pagination.page,
      size: pagination.pageSize,
      // 搜索关键词
      search: filters.search && filters.search.trim() ? filters.search.trim() : undefined,
      // 项目筛选
      project_id: filters.project_id || undefined,
      // 版本筛选
      version_id: filters.version_id || undefined,
      // 负责人筛选
      assignee_id: filters.assignee_id || undefined,
      // 状态筛选
      status: filters.status || undefined,
      // 优先级筛选
      priority: filters.priority || undefined,
      // 日期范围筛选
      due_date_from: filters.due_date_from || undefined,
      due_date_to: filters.due_date_to || undefined,
      // 排序
      sort_by: sortConfig.prop ? (sortConfig.prop === 'task_type' ? 'type' : sortConfig.prop) : undefined,
      sort_order: sort_order
    }
    
    const response = await getTasks(params)
    const parsedResponse = ResponseParser.parseTaskListResponse(response)
    tasks.value = parsedResponse.items
    pagination.total = parsedResponse.total
    
    // 批量收集所有需要的用户ID并获取用户信息
    await loadUsersForTasks(tasks.value)
    
  } catch (error) {
    console.error('获取任务列表失败:', error)
    const errorMessage = ResponseParser.extractMessage(error) || '获取任务列表失败'
    ElMessage.error(errorMessage)
  } finally {
    loading.value = false
    if (isRefresh) {
      setTimeout(() => {
        initialLoading.value = false
        isRefreshing.value = false
      }, 300)
    } else if (initialLoading.value) {
      initialLoading.value = false
    }
  }
}

// 获取任务统计
const fetchTaskStats = async () => {
  try {
    // 只有当project_id不为空时才传递该参数
    const params: { project_id?: string } = {}
    if (filters.project_id && filters.project_id.trim() !== '') {
      params.project_id = filters.project_id
    }
    
    const response = await getTaskStats(params)
    const parsedResponse = ResponseParser.parseStatsResponse(response)
    console.log('任务统计解析结果:', parsedResponse)
    
    if (parsedResponse.success && parsedResponse.stats) {
      const stats = parsedResponse.stats as any
      
      // 使用 tasks_by_status（动态状态统计）
      if (stats.tasks_by_status) {
        // 更新动态状态统计
        taskStats.tasks_by_status = { ...stats.tasks_by_status }
        
        // 动态获取完成状态代码并计算完成数量
        const completedStatuses = taskStatusOptions.value
          .filter(state => {
            const name = state.label?.toLowerCase() || ''
            const code = state.value?.toLowerCase() || ''
            return name.includes('完成') || name.includes('已完成') ||
                   code.includes('done') || code.includes('completed') || code.includes('finished')
          })
          .map(state => state.value)
        
        const completedCount = completedStatuses.reduce((sum, code) => {
          return sum + (stats.tasks_by_status[code] || 0)
        }, 0)
        
        // 保留 completed 字段用于兼容
        if (!('completed' in taskStats)) {
          (taskStats as any).completed = completedCount
        }
      } else {
        // 兼容旧格式（如果后端返回了旧格式）
        taskStats.tasks_by_status = {}
      }
      
      // 确保总数正确
      if (stats.total !== undefined) {
        taskStats.total = stats.total
      }
      
      console.log('任务统计数据更新后:', taskStats)
    } else {
      console.error('任务统计数据解析失败:', parsedResponse)
      ElMessage.error(parsedResponse.message || '获取任务统计失败')
    }
  } catch (error) {
    console.error('获取任务统计失败:', error)
    const errorMessage = ResponseParser.extractMessage(error) || '获取任务统计失败'
    ElMessage.error(errorMessage)
  }
}

// 将项目成员转换为用户格式
const convertProjectMembersToUsers = (members: ProjectMember[]): User[] => {
  return members.map(member => ({
    id: member.user_id,
    username: member.username || member.user_name || '',
    name: member.name || member.username || member.user_name || '',
    email: member.email || member.user_email || '',
    avatar: member.avatar,
    roles: member.roles || (member.role ? [member.role] : []),
    status: 'active' as const,
    is_verified: false,
    created_at: member.joined_at,
    updated_at: member.joined_at
  }))
}

// 根据项目ID获取用户列表（项目成员）
const loadUsersByProject = async (projectId?: string): Promise<User[]> => {
  if (!projectId) {
    // 如果没有项目ID，返回空数组
    return []
  }

  try {
    const response = await getProjectMembers(projectId)
    if (response.success && response.data) {
      // 处理不同的响应格式
      let members: ProjectMember[] = []
      
      // getProjectMembers 返回 ApiResponse<ProjectMember[]>
      // 所以 response.data 应该是 ProjectMember[] 数组
      if (Array.isArray(response.data)) {
        // 如果 data 直接是数组
        members = response.data
      } else if (response.data && typeof response.data === 'object') {
        // 如果 data 是对象，可能是包装格式
        const dataObj = response.data as Record<string, any>
        if ('members' in dataObj && Array.isArray(dataObj.members)) {
          // 如果 data 是对象，包含 members 字段（实际后端返回格式）
          members = dataObj.members
        } else if (Array.isArray(dataObj)) {
          // 如果 dataObj 本身是数组（虽然不太可能，但为了类型安全）
          members = dataObj as ProjectMember[]
        }
      }
      
      return convertProjectMembersToUsers(members)
    }
    return []
  } catch (error) {
    console.error('获取项目成员失败:', error)
    return []
  }
}

// 批量加载任务中需要的用户信息
const loadUsersForTasks = async (taskList: Task[]) => {
  // 收集所有需要的用户ID
  const userIds = new Set<string>()
  taskList.forEach(task => {
    if (task.assignee_id) userIds.add(task.assignee_id)
    if (task.reporter_id) userIds.add(task.reporter_id)
    if (task.created_by) userIds.add(task.created_by)
  })
  
  // 如果已经有用户列表，先从列表中查找
  const existingUsers = new Map<string, User>()
  users.value.forEach(user => {
    if (userIds.has(user.id)) {
      existingUsers.set(user.id, user)
      usersMap.value.set(user.id, user)
    }
  })
  
  // 找出还需要获取的用户ID
  const missingUserIds = Array.from(userIds).filter(id => !existingUsers.has(id))
  
  if (missingUserIds.length > 0) {
    try {
      // 优先使用项目成员
      const projectId = filters.project_id
      if (projectId) {
        const projectUsers = await loadUsersByProject(projectId)
        projectUsers.forEach(user => {
          if (userIds.has(user.id)) {
            usersMap.value.set(user.id, user)
            if (!users.value.find(u => u.id === user.id)) {
              users.value.push(user)
            }
          }
        })
      } else {
        // 如果没有项目ID，使用系统用户
        const usersResponse = await getUsers({ page: 1, size: 200 })
        const parsedUsers = ResponseParser.parseUserListResponse(usersResponse)
        
        // 更新用户列表和映射
        parsedUsers.items.forEach(user => {
          if (userIds.has(user.id)) {
            usersMap.value.set(user.id, user)
            if (!users.value.find(u => u.id === user.id)) {
              users.value.push(user)
            }
          }
        })
      }
    } catch (error) {
      console.warn('批量获取用户信息失败，将使用任务中已有的用户信息:', error)
    }
  }
}

// 获取基础数据
const fetchBaseData = async (forceRefresh = false) => {
  try {
    // 加载任务选项（状态和优先级）和标签（这些不依赖项目）
    await Promise.all([
      loadTaskStates(),
      loadTaskOptions(),
      tagsStore.fetchTags().catch(err => {
        console.warn('加载系统标签失败，将使用任务中的标签:', err)
        return []
      })
    ])
    
    // 获取项目列表
    const projectsResponse = await getProjects({ page: 1, size: 100 })
    if (projectsResponse && projectsResponse.success) {
      // 使用 ResponseParser 统一解析项目列表响应
      const parsedProjects = ResponseParser.parseProjectListResponse(projectsResponse)
      projects.value = parsedProjects.items
      
      // 如果项目列表加载完成且没有选择项目，默认选择第一个项目
      // 注意：这里只设置项目ID，不加载相关数据，避免与后续初始化流程重复
      // 但在刷新时（forceRefresh=true），如果当前项目不在新列表中，需要重新选择
      if (projects.value.length > 0) {
        if (!filters.project_id) {
          // 没有选择项目，选择第一个
          const firstProject = projects.value[0]
          filters.project_id = firstProject.id
        } else if (forceRefresh) {
          // 刷新时，检查当前项目是否还在列表中
          const currentProjectExists = projects.value.some((p: Project) => p.id === filters.project_id)
          if (!currentProjectExists) {
            // 当前项目不存在，选择第一个项目
            const firstProject = projects.value[0]
            filters.project_id = firstProject.id
          }
        }
      }
    }
    
    // 注意：不在这里调用 refreshUsers 和 fetchVersions，避免重复调用
    // 这些会在 onMounted 或 handleRefresh 中统一处理
  } catch (error) {
    console.error('获取基础数据失败:', error)
    ElMessage.error('获取基础数据失败')
  }
}


// 项目变化处理
const handleProjectChange = async (projectId: string | null | undefined) => {
  // 确保 projectId 是字符串类型
  const projectIdStr = projectId ? String(projectId) : ''
  
  // 更新 filters.project_id
  filters.project_id = projectIdStr || undefined
  
  if (projectIdStr) {
    // 刷新用户列表（项目成员）
    await refreshUsers()
    // 刷新版本列表
    await fetchVersions(projectIdStr)
    // 刷新任务列表
    await fetchTasks()
    await fetchTaskStats()
  } else {
    // 如果清空项目，清空用户列表和任务列表
    users.value = []
    usersMap.value.clear()
    tasks.value = []
    filters.version_id = undefined
  }
}

// 监听项目变化，更新版本列表和用户列表
// 使用 immediate: false 避免初始化时触发
projectIdWatcher.value = watch(() => filters.project_id, async (newProjectId, oldProjectId) => {
  // 如果项目变化（且不是初始化时的第一次设置），重置版本选择并刷新数据
  if (newProjectId !== oldProjectId && oldProjectId !== undefined) {
    filters.version_id = undefined
    
    // 调用统一的fetchVersions函数
    await fetchVersions(newProjectId || undefined)
    
    // 刷新用户列表（项目成员）
    await refreshUsers()
  }
}, { immediate: false })

// 事件处理
const handleFilterApply = async (newFilters: Partial<TaskFilters>) => {
  Object.assign(filters, newFilters)
  pagination.page = 1
  await fetchTasks()
  await fetchTaskStats()
}

const handleFilterReset = async () => {
  Object.assign(filters, {
    search: undefined,
    project_id: undefined,
    version_id: undefined,
    status: undefined,
    priority: undefined,
    assignee_id: undefined,
    due_date_from: undefined,
    due_date_to: undefined
  })
  pagination.page = 1
  await fetchTasks()
  await fetchTaskStats()
}


const handleOpenCreate = () => {
  if (!selectedProjectId.value) {
    ElMessage.warning('请先选择项目')
    return
  }
  quickCreateStatus.value = ''
  createDialogVisible.value = true
}

const handleCreateTaskFromKanban = (status: string) => {
  if (!selectedProjectId.value) {
    ElMessage.warning('请先选择项目')
    return
  }
  quickCreateStatus.value = status
  createDialogVisible.value = true
}

const handleSelectionChange = (ids: string[]) => {
  selectedIds.value = ids
}

const handleOpenDetail = (id: string) => {
  if (!id) return
  selectedTaskId.value = id
  detailDialogVisible.value = true
}

const handleTaskCreated = () => {
  fetchTasks()
  createDialogVisible.value = false
}

const handleTaskUpdated = () => {
  fetchTasks()
}

const handleDetailDialogClose = (visible: boolean) => {
  detailDialogVisible.value = visible
  if (!visible) {
    selectedTaskId.value = ''
  }
}

const handleDelete = async (id: string) => {
  try {
    await ElMessageBox.confirm(
      '确定要删除该任务吗？删除后无法恢复。',
      '确认删除',
      {
        confirmButtonText: '确定',
        cancelButtonText: '取消',
        type: 'warning'
      }
    )
    
    const response = await deleteTask(id)
    if (ResponseParser.isSuccess(response)) {
      ElMessage.success('删除成功')
      // 刷新任务列表
      await fetchTasks()
    } else {
      const errorMessage = ResponseParser.extractMessage(response) || '删除失败'
      ElMessage.error(errorMessage)
    }
  } catch (error: any) {
    if (error !== 'cancel') {
      console.error('删除任务失败:', error)
      const errorMessage = ResponseParser.extractMessage(error) || '删除任务失败'
      ElMessage.error(errorMessage)
    }
  }
}

const handleRefresh = async () => {
  try {
    // 标记为刷新状态并显示加载状态
    isRefreshing.value = true
    initialLoading.value = true
    
    // 先刷新基础数据（项目列表、任务选项、标签）
    await fetchBaseData(true)
    
    // 然后刷新项目相关数据和任务数据
    const refreshPromises: Promise<any>[] = [
      // 刷新任务列表和统计
      fetchTasks(true),
      fetchTaskStats()
    ]
    
    // 如果已选择项目，刷新项目相关数据（成员、版本）
    if (filters.project_id) {
      refreshPromises.push(
        refreshUsers(),
        fetchVersions(filters.project_id)
      )
    }
    
    // 并行执行所有刷新操作
    await Promise.all(refreshPromises)
    
    ElMessage.success('刷新成功')
  } catch (error) {
    console.error('刷新失败:', error)
    ElMessage.error('刷新失败，请稍后重试')
  } finally {
    // 延迟一点隐藏加载状态，让动画更自然
    setTimeout(() => {
      initialLoading.value = false
      isRefreshing.value = false
    }, 300)
  }
}

// 子任务拆分相关状态
const taskSplitDialogVisible = ref(false)
const taskSplitTask = ref<{ id: string; project_id: string; title: string } | null>(null)

// 处理子任务拆分
const handleSplitTask = (task: any) => {
  if (!task || !task.id) {
    ElMessage.warning('无法识别任务信息')
    return
  }
  
  taskSplitTask.value = {
    id: task.id,
    project_id: task.project_id || '',
    title: task.title || ''
  }
  taskSplitDialogVisible.value = true
}

// 子任务创建成功后的处理
const handleSubTaskCreated = async () => {
  taskSplitTask.value = null
  taskSplitDialogVisible.value = false
  await fetchTasks()
  await fetchTaskStats()
}

const handleUpdateStatus = async (id: string, status: string) => {
  if (!id || !status) return
  try {
    const response = await updateTaskStatus(id, status as TaskStatus)
    if (ResponseParser.isSuccess(response)) {
      // 如果响应中包含任务数据，立即更新列表中的对应任务
      const responseData = response.data
      if (responseData && typeof responseData === 'object' && 'id' in responseData) {
        const updatedTask = responseData as Task
        const taskIndex = tasks.value.findIndex(t => t.id === id)
        if (taskIndex !== -1) {
          // 更新列表中的任务，保留其他字段
          tasks.value[taskIndex] = {
            ...tasks.value[taskIndex],
            ...updatedTask
          }
          ElMessage.success('状态更新成功')
        } else {
          // 如果任务不在当前列表中，刷新列表
          await fetchTasks()
          ElMessage.success('状态更新成功')
        }
      } else {
        // 如果响应中没有任务数据，刷新列表
        await fetchTasks()
        ElMessage.success('状态更新成功')
      }
    } else {
      const errorMessage = ResponseParser.extractMessage(response) || '状态更新失败'
      ElMessage.error(errorMessage)
    }
  } catch (error) {
    console.error('更新状态失败:', error)
    const errorMessage = ResponseParser.extractMessage(error) || '更新状态失败'
    ElMessage.error(errorMessage)
  }
}

const handleUpdatePriority = async (id: string, priority: string) => {
  if (!id || !priority) return
  try {
    const response = await updateTaskPriority(id, priority)
    if (ResponseParser.isSuccess(response)) {
      ElMessage.success('优先级更新成功')
      await fetchTasks()
    } else {
      const errorMessage = ResponseParser.extractMessage(response) || '优先级更新失败'
      ElMessage.error(errorMessage)
    }
  } catch (error) {
    console.error('更新优先级失败:', error)
    const errorMessage = ResponseParser.extractMessage(error) || '更新优先级失败'
    ElMessage.error(errorMessage)
  }
}

const handleUpdateAssignee = async (id: string, assigneeId: string | null) => {
  if (!id) return
  try {
    const response = await assignTask(id, assigneeId || '')
    if (ResponseParser.isSuccess(response)) {
      ElMessage.success('负责人更新成功')
      await fetchTasks()
    } else {
      const errorMessage = ResponseParser.extractMessage(response) || '负责人更新失败'
      ElMessage.error(errorMessage)
    }
  } catch (error) {
    console.error('更新负责人失败:', error)
    const errorMessage = ResponseParser.extractMessage(error) || '更新负责人失败'
    ElMessage.error(errorMessage)
  }
}

const handlePageChange = async (page: number) => {
  pagination.page = page
  await fetchTasks()
}

const handlePageSizeChange = async (size: number) => {
  pagination.pageSize = size
  pagination.page = 1
  await fetchTasks()
}

// 处理排序变化
const handleSortChange = async (prop: string, order: string) => {
  sortConfig.prop = prop
  sortConfig.order = order
  pagination.page = 1 // 排序时重置到第一页
  await fetchTasks()
}

const toggleFilterCollapsed = () => {
  filterCollapsed.value = !filterCollapsed.value
}

const viewModeProxy = computed({
  get: () => viewMode.value,
  set: (value) => {
    viewMode.value = value as 'list' | 'kanban'
  }
})

// 批量操作相关函数
const ensureSelection = () => {
  if (!selectedIds.value.length) {
    ElMessage.warning('请先选择任务')
    return false
  }
  return true
}

const promptSelect = async (options: Array<{ value: string; label: string }>, title: string, placeholder: string) => {
  const selected = ref(options[0]?.value ?? '')

  try {
    await ElMessageBox({
      title: title,
      message: h(
        'div',
        { class: 'prompt-select-wrapper' },
        [
          h('div', { class: 'select-hint' }, `已选择 ${selectedIds.value.length} 项任务`),
          h('div', { class: 'select-label' }, '请选择要设置的值：'),
          h(
            ElSelect,
            {
              modelValue: selected.value,
              placeholder,
              style: 'width: 100%;',
              size: 'large',
              filterable: options.length > 5,
              'onUpdate:modelValue': (value: string) => {
                selected.value = value
              }
            },
            () =>
              options.map(option =>
                h(ElOption, {
                  key: option.value,
                  label: option.label,
                  value: option.value
                })
              )
          )
        ]
      ),
      showCancelButton: true,
      confirmButtonText: '确定',
      cancelButtonText: '取消',
      customClass: 'batch-operation-dialog',
      beforeClose: (action, _instance, done) => {
        if (action === 'confirm') {
          if (!selected.value) {
            ElMessage.warning('请选择一个值')
            return
          }
          done()
        } else {
          done()
        }
      }
    })
    return selected.value
  } catch {
    return null
  }
}

const handleClearSelection = () => {
  selectedIds.value = []
}

const handleBatchUpdateStatus = async () => {
  if (!ensureSelection()) return
  if (!selectedProjectId.value) {
    ElMessage.warning('请先选择项目')
    return
  }
  
  const statusValue = await promptSelect(taskStatuses.value, '批量更新状态', '请选择状态')
  if (!statusValue) return

  batchLoading.value = true
  try {
    const response = await batchUpdateTasks(selectedIds.value.slice(), { status: statusValue })
    if (ResponseParser.isSuccess(response)) {
      ElMessage.success('批量更新状态成功')
      await fetchTasks()
      handleClearSelection()
    } else {
      ElMessage.error(ResponseParser.extractMessage(response) || '批量更新状态失败')
    }
  } catch (error) {
    console.error('批量更新状态失败', error)
    ElMessage.error('批量更新状态失败，请稍后重试')
  } finally {
    batchLoading.value = false
  }
}

const handleBatchUpdatePriority = async () => {
  if (!ensureSelection()) return
  if (!selectedProjectId.value) {
    ElMessage.warning('请先选择项目')
    return
  }
  
  const priorityValue = await promptSelect(priorityOptionsForFilter.value, '批量更新优先级', '请选择优先级')
  if (!priorityValue) return

  batchLoading.value = true
  try {
    const response = await batchUpdateTasks(selectedIds.value.slice(), { priority: priorityValue })
    if (ResponseParser.isSuccess(response)) {
      ElMessage.success('批量更新优先级成功')
      await fetchTasks()
      handleClearSelection()
    } else {
      ElMessage.error(ResponseParser.extractMessage(response) || '批量更新优先级失败')
    }
  } catch (error) {
    console.error('批量更新优先级失败', error)
    ElMessage.error('批量更新优先级失败，请稍后重试')
  } finally {
    batchLoading.value = false
  }
}

const handleBatchAssign = async () => {
  if (!ensureSelection()) return
  if (!selectedProjectId.value) {
    ElMessage.warning('请先选择项目')
    return
  }
  if (users.value.length === 0) {
    ElMessage.warning('当前项目暂无成员，无法分配负责人')
    return
  }
  
  const assigneeValue = await promptSelect(
    users.value.map(u => ({ value: u.id, label: u.name || u.username || '' })),
    '批量分配负责人',
    '请选择负责人'
  )
  if (!assigneeValue) return

  batchLoading.value = true
  try {
    const response = await batchUpdateTasks(selectedIds.value.slice(), { assignee_id: assigneeValue })
    if (ResponseParser.isSuccess(response)) {
      ElMessage.success('批量分配成功')
      await fetchTasks()
      handleClearSelection()
    } else {
      ElMessage.error(ResponseParser.extractMessage(response) || '批量分配失败')
    }
  } catch (error) {
    console.error('批量分配失败', error)
    ElMessage.error('批量分配失败，请稍后重试')
  } finally {
    batchLoading.value = false
  }
}

const handleBatchUpdateReporter = async () => {
  if (!ensureSelection()) return
  
  ElMessage.warning('任务模块暂不支持批量更新报告人')
}

const handleBatchUpdateProject = async () => {
  if (!ensureSelection()) return
  
  const projectValue = await promptSelect(
    projects.value.map(p => ({ value: p.id, label: p.name })),
    '批量更新所属项目',
    '请选择项目'
  )
  if (!projectValue) return

  batchLoading.value = true
  try {
    // 注意：任务API可能没有project_id字段，需要根据实际API调整
    ElMessage.warning('任务模块暂不支持批量更新项目')
  } catch (error) {
    console.error('批量更新所属项目失败', error)
    ElMessage.error('批量更新所属项目失败，请稍后重试')
  } finally {
    batchLoading.value = false
  }
}

const handleBatchDelete = async () => {
  if (!ensureSelection()) return
  
  try {
    await ElMessageBox.confirm(
      `确定要删除选中的 ${selectedIds.value.length} 项任务吗？删除后无法恢复。`,
      '批量删除确认',
      {
        confirmButtonText: '确定',
        cancelButtonText: '取消',
        type: 'warning'
      }
    )
  } catch {
    return
  }

  batchLoading.value = true
  try {
    const response = await batchDeleteTasks(selectedIds.value.slice())
    if (ResponseParser.isSuccess(response)) {
      ElMessage.success('批量删除成功')
      await fetchTasks()
      handleClearSelection()
    } else {
      ElMessage.error(ResponseParser.extractMessage(response) || '批量删除失败')
    }
  } catch (error) {
    console.error('批量删除失败', error)
    ElMessage.error('批量删除失败，请稍后重试')
  } finally {
    batchLoading.value = false
  }
}

// 导入导出相关函数
const handleDownloadTemplate = async () => {
  try {
    batchLoading.value = true
    const response = await downloadImportTemplate()
    
    const blob = new Blob([response.data], {
      type: 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet'
    })
    const url = window.URL.createObjectURL(blob)
    const link = document.createElement('a')
    link.href = url
    
    const contentDisposition = response.headers['content-disposition']
    let filename = `tasks_template_${new Date().getTime()}.xlsx`
    if (contentDisposition) {
      const filenameMatch = contentDisposition.match(/filename[^;=\n]*=((['"]).*?\2|[^;\n]*)/)
      if (filenameMatch && filenameMatch[1]) {
        filename = filenameMatch[1].replace(/['"]/g, '')
        try {
          filename = decodeURIComponent(escape(filename))
        } catch {
          // 如果解码失败，使用原始文件名
        }
      }
    }
    
    link.download = filename
    document.body.appendChild(link)
    link.click()
    document.body.removeChild(link)
    window.URL.revokeObjectURL(url)
    
    ElMessage.success('模板下载成功')
  } catch (error) {
    console.error('下载模板失败:', error)
    const errorMessage = ResponseParser.extractMessage(error) || '下载模板失败'
    ElMessage.error(errorMessage)
  } finally {
    batchLoading.value = false
  }
}

const handleImportFile = async (file: any) => {
  try {
    batchLoading.value = true
    
    const fileType = file.raw.type
    const fileName = file.name
    const validTypes = [
      'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet',
      'application/vnd.ms-excel'
    ]
    
    if (!validTypes.includes(fileType) && !fileName.endsWith('.xlsx') && !fileName.endsWith('.xls')) {
      ElMessage.error('只支持 Excel 文件 (.xlsx, .xls)')
      batchLoading.value = false
      return
    }

    await ElMessageBox.confirm(
      `确定要导入文件 "${fileName}" 吗？\n导入前请确保文件格式正确，包含必需的列（标题、项目）。`,
      '确认导入',
      {
        confirmButtonText: '确定',
        cancelButtonText: '取消',
        type: 'warning'
      }
    )
    
    const response = await importTasks(file.raw)
    const parsedResponse = ResponseParser.parseResponse(response)
    
    if (parsedResponse.success) {
      const data = parsedResponse.data as any
      const successCount = data?.success_count || 0
      const errorCount = data?.error_count || 0
      const errors = data?.errors || []
      
      let message = `导入完成: 成功 ${successCount} 条`
      if (errorCount > 0) {
        message += `, 失败 ${errorCount} 条`
        
        const errorPreview = errors.slice(0, 10).join('\n')
        const moreErrors = errors.length > 10 ? `\n... 还有 ${errors.length - 10} 个错误` : ''
        
        ElMessageBox.alert(
          `${message}\n\n错误详情:\n${errorPreview}${moreErrors}`,
          '导入结果',
          {
            confirmButtonText: '确定',
            type: errorCount > 0 ? 'warning' : 'success',
            dangerouslyUseHTMLString: false
          }
        )
      } else {
        ElMessage.success(message)
      }
      
      await fetchTasks()
    } else {
      ElMessage.error(parsedResponse.message || '导入失败')
    }
  } catch (error: any) {
    if (error !== 'cancel') {
      console.error('导入任务失败:', error)
      const errorMessage = ResponseParser.extractMessage(error) || '导入任务失败'
      ElMessage.error(errorMessage)
    }
  } finally {
    batchLoading.value = false
  }
}

const handleExportTasks = async () => {
  try {
    batchLoading.value = true
    
    const exportParams: any = {}
    
    if (selectedIds.value && selectedIds.value.length > 0) {
      exportParams.task_ids = selectedIds.value.join(',')
    } else {
      if (filters.search && filters.search.trim()) {
        exportParams.search = filters.search.trim()
      }
      if (filters.project_id && filters.project_id.trim()) {
        exportParams.project_id = filters.project_id.trim()
      }
      if (filters.version_id && filters.version_id.trim()) {
        exportParams.version_id = filters.version_id.trim()
      }
      if (filters.status) {
        exportParams.status = filters.status
      }
      if (filters.priority) {
        exportParams.priority = filters.priority
      }
      if (filters.assignee_id && filters.assignee_id.trim()) {
        exportParams.assignee_id = filters.assignee_id.trim()
      }
      if (filters.due_date_from) {
        exportParams.due_date_from = filters.due_date_from
      }
      if (filters.due_date_to) {
        exportParams.due_date_to = filters.due_date_to
      }
    }
    
    const response = await exportTasks(exportParams)
    
    const blob = new Blob([response.data], {
      type: 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet'
    })
    const url = window.URL.createObjectURL(blob)
    const link = document.createElement('a')
    link.href = url
    
    const contentDisposition = response.headers['content-disposition']
    let filename = `tasks_export_${new Date().getTime()}.xlsx`
    if (contentDisposition) {
      const filenameMatch = contentDisposition.match(/filename[^;=\n]*=((['"]).*?\2|[^;\n]*)/)
      if (filenameMatch && filenameMatch[1]) {
        filename = filenameMatch[1].replace(/['"]/g, '')
        try {
          filename = decodeURIComponent(escape(filename))
        } catch {
          // 如果解码失败，使用原始文件名
        }
      }
    }
    
    link.download = filename
    document.body.appendChild(link)
    link.click()
    document.body.removeChild(link)
    window.URL.revokeObjectURL(url)
    
    if (selectedIds.value && selectedIds.value.length > 0) {
      ElMessage.success(`导出成功：已导出 ${selectedIds.value.length} 项选中的任务`)
    } else {
      ElMessage.success('导出成功：已导出全部任务数据')
    }
  } catch (error) {
    console.error('导出任务失败:', error)
    const errorMessage = ResponseParser.extractMessage(error) || '导出任务失败'
    ElMessage.error(errorMessage)
  } finally {
    batchLoading.value = false
  }
}

// 初始化
onMounted(async () => {
  try {
    // 获取基础数据（包括项目列表和任务选项）
    await fetchBaseData()
    
    // 确保有项目被选中（如果项目列表已加载但还没有选择项目）
    if (!filters.project_id && projects.value.length > 0) {
      const firstProject = projects.value[0]
      filters.project_id = firstProject.id
    }
    
    // 如果已选择项目，加载项目相关的数据（成员和版本）
    if (filters.project_id) {
      await Promise.all([
        refreshUsers(),
        fetchVersions(filters.project_id)
      ])
    }
    
    // 加载任务列表和统计
    await Promise.all([
      fetchTasks(),
      fetchTaskStats()
    ])
  } catch (error) {
    console.error('加载任务数据失败:', error)
    ElMessage.error('加载数据失败，请稍后重试')
  } finally {
    initialLoading.value = false
  }
})

</script>

<style scoped lang="scss">
.prompt-select-wrapper {
  padding-top: 8px;
  
  .select-hint {
    font-size: 13px;
    color: #909399;
    margin-bottom: 16px;
    padding: 8px 12px;
    background: #f0f9ff;
    border-left: 3px solid #409eff;
    border-radius: 4px;
    display: inline-flex;
    align-items: center;
    gap: 6px;
    
    &::before {
      content: '';
      display: inline-block;
      width: 6px;
      height: 6px;
      border-radius: 50%;
      background: #409eff;
    }
  }
  
  .select-label {
    font-size: 14px;
    color: #606266;
    margin-bottom: 12px;
    font-weight: 500;
  }
}
</style>

<style lang="scss">
/* 批量操作弹窗全局样式 */
.batch-operation-dialog {
  border-radius: 12px;
  overflow: hidden;
  width: 480px;
}

.batch-operation-dialog .el-message-box__header {
  padding: 20px 24px 16px;
  border-bottom: 1px solid #ebeef5;
  background: linear-gradient(135deg, #f8fbff 0%, #ffffff 100%);
}

.batch-operation-dialog .el-message-box__title {
  font-size: 18px;
  font-weight: 600;
  color: #303133;
  line-height: 1.4;
}

.batch-operation-dialog .el-message-box__headerbtn {
  top: 20px;
  right: 20px;
}

.batch-operation-dialog .el-message-box__headerbtn .el-message-box__close {
  color: #909399;
  font-size: 18px;
}

.batch-operation-dialog .el-message-box__headerbtn .el-message-box__close:hover {
  color: #606266;
}

.batch-operation-dialog .el-message-box__content {
  padding: 24px;
  background: #ffffff;
}

.batch-operation-dialog .el-message-box__message {
  margin: 0;
  padding: 0;
}

.batch-operation-dialog .el-message-box__btns {
  padding: 16px 24px;
  border-top: 1px solid #ebeef5;
  background: #fafbfc;
}

.batch-operation-dialog .el-message-box__btns .el-button {
  padding: 10px 20px;
  border-radius: 6px;
  font-size: 14px;
  font-weight: 500;
  transition: all 0.2s;
}

.batch-operation-dialog .el-message-box__btns .el-button--default {
  border-color: #dcdfe6;
  color: #606266;
  background: #ffffff;
}

.batch-operation-dialog .el-message-box__btns .el-button--default:hover {
  color: #409eff;
  border-color: #c6e2ff;
  background: #ecf5ff;
}

.batch-operation-dialog .el-message-box__btns .el-button--primary {
  background: #409eff;
  border-color: #409eff;
}

.batch-operation-dialog .el-message-box__btns .el-button--primary:hover {
  background: #66b1ff;
  border-color: #66b1ff;
}

.batch-operation-dialog .el-message-box__btns .el-button--primary:active {
  background: #3a8ee6;
  border-color: #3a8ee6;
}
</style>

<style scoped lang="scss">
.tasks-workspace {
  display: flex;
  flex-direction: column;
  gap: 16px;
  padding: 16px 24px;
  background: #f4f6fb;
  height: 100%;
  min-height: 0;
  overflow: hidden;
  position: relative;
}

.workspace-header {
  display: flex;
  justify-content: space-between;
  align-items: flex-start;
  gap: 16px;
  padding: 20px 24px;
  border-radius: 16px;
  background: linear-gradient(135deg, #ffffff 0%, #f8fbff 100%);
  box-shadow: 0 12px 32px rgba(36, 61, 99, 0.08);
  flex-shrink: 0;
}

.header-left .title-block h2 {
  margin: 0;
  font-size: 24px;
  font-weight: 600;
  color: #1f2a44;
}

.header-left .subtitle {
  margin: 6px 0 0;
  font-size: 14px;
  color: #607089;
}

.header-left {
  display: flex;
  flex-direction: column;
  gap: 12px;
  flex: 1;
}

.header-right {
  display: flex;
  gap: 12px;
  align-items: center;
}

.project-selector-wrapper {
  display: flex;
  align-items: center;
  gap: 8px;
  margin-right: 8px;
}

.project-label {
  font-size: 14px;
  color: #606266;
  font-weight: 500;
  white-space: nowrap;
}

.project-selector {
  min-width: 180px;
}

.view-switcher {
  background: #eef3ff;
  border-radius: 12px;
}

.refresh-button {
  display: flex;
  align-items: center;
  gap: 6px;
}

.create-button {
  display: flex;
  align-items: center;
  gap: 6px;
}

.workspace-main {
  margin-top: 0;
  display: flex;
  gap: 16px;
  flex: 1;
  min-height: 0;
  min-width: 0;
  overflow: hidden;
  height: 100%;
}

.filter-panel {
  width: 300px;
  position: relative;
  transition: width 0.24s ease, transform 0.24s ease;
  flex-shrink: 0;
  max-width: 400px;
  display: flex;
  flex-direction: column;
  height: 100%;
  min-height: 0;
  overflow: hidden;
}

.filter-panel.is-collapsed {
  width: 60px;
  transform: translateX(-12px);
}

.filter-panel.is-collapsed .filter-body {
  display: none;
}

.filter-panel.is-collapsed .filter-header {
  flex-direction: column;
  align-items: center;
  gap: 8px;
  padding: 12px 8px;
}

.filter-panel.is-collapsed .filter-header h3 {
  writing-mode: vertical-rl;
  margin: 0;
  letter-spacing: 4px;
}

.filter-header {
  display: flex;
  justify-content: space-between;
  align-items: center;
  padding: 12px 16px;
  background: #ffffff;
  border-radius: 16px;
  box-shadow: 0 10px 24px rgba(33, 51, 96, 0.06);
  margin-bottom: 12px;
  flex-shrink: 0;
}

.filter-header h3 {
  margin: 0;
  font-size: 15px;
  color: #2b3c5c;
  font-weight: 600;
}

.collapse-btn {
  color: #4b5e89;
}

.filter-body {
  background: #ffffff;
  border-radius: 16px;
  box-shadow: 0 10px 24px rgba(33, 51, 96, 0.06);
  padding: 16px 18px;
  overflow-y: auto;
  overflow-x: hidden;
  flex: 1;
  min-height: 0;
  max-height: 100%;
  
  &::-webkit-scrollbar {
    width: 6px;
  }
  
  &::-webkit-scrollbar-thumb {
    background: #c1c1c1;
    border-radius: 3px;
    
    &:hover {
      background: #a8a8a8;
    }
  }
  
  &::-webkit-scrollbar-track {
    background: #f1f1f1;
    border-radius: 3px;
  }
}

.workspace-content {
  display: flex;
  flex-direction: column;
  gap: 12px;
  flex: 1;
  min-height: 0;
  min-width: 0;
  overflow: hidden;
}

.workspace-body {
  flex: 1;
  min-height: 0;
  min-width: 0;
  overflow: hidden;
  width: 100%;
  display: flex;
  flex-direction: column;
}

.fade-slide-enter-active,
.fade-slide-leave-active {
  transition: all 0.28s ease;
}

.fade-slide-enter-from,
.fade-slide-leave-to {
  opacity: 0;
  transform: translateY(12px) scale(0.99);
}
</style>
